import json
import requests
from config import *



# 动态添加拉流代理（支持 rtsp/rtmp/hls 等）
async def addStreamProxy(request):
    data = await request.post()
    url = data.get('url')
    url_name = data.get('url_name',None)

    if not url:
        return web.json_response({'code': 400, 'msg': '缺少参数：url'})

    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/addStreamProxy"
    stream = generate_mixed_id()

    params = {
        'secret': ZLK_SECRET,
        'vhost': ZLK_HOST,
        'app': 'openUrl',
        'stream': stream,
        'url': url,
        'enable_rtsp': True,
        'enable_hls': True,
        'enable_hls_fmp4': True,
        'enable_rtmp': True,
        'enable_ts': True,
        'enable_fmp4': True,
    }

    try:

        # 先查询是否已存在该流地址
        async with AsyncSessionLocal() as session:
            result = await session.execute(
                select(Zlk_data).where(Zlk_data.cameras_rtsp == url)
            )
            existing = result.scalar_one_or_none()
            # 如果数据库记录（cameras_rtsp）存在不添加记录-返回
            if existing:
                return web.json_response({
                    'code': 400,
                    'msg': '该地址已存在，无需重复添加',
                    'data': {
                        'rtsp': existing.zlk_rtsp,
                        'rtmp': existing.zlk_rtmp,
                        'mp4': existing.zlk_mp4,
                        'ts': existing.zlk_ts,
                        'flv': existing.zlk_flv,
                        'key': existing.zlk_key
                    }
                })

        res = requests.get(api, params=params, timeout=3)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应非 JSON 格式'})

        if zlk_info.get('code') == 0 and zlk_info.get('data', {}).get('key'):

            # -->如果存在走如下逻辑
            # ✅ 写入数据库
            async with AsyncSessionLocal() as session:
                async with session.begin():
                    stream_data = Zlk_data(
                        cameras_name=url_name,
                        cameras_rtsp=url,
                        zlk_app='openUrl',
                        zlk_live=stream,
                        zlk_key=zlk_info['data']['key'],
                        zlk_mp4=SE_VIDEO+'/openUrl'+'/{}'.format(stream)+'.live.mp4',
                        zlk_rtmp=SE_RTMP+'/openUrl'+'/{}'.format(stream),
                        zlk_rtsp=SE_RTSP+'/openUrl'+'/{}'.format(stream),
                        zlk_ts=SE_VIDEO+'/openUrl'+'/{}'.format(stream)+'.live.ts',
                        zlk_flv=SE_VIDEO+'/openUrl'+'/{}'.format(stream)+'.live.flv',
                    )
                    session.add(stream_data)
                await session.commit()

            return web.json_response({
                'code': 200,
                'msg': '拉流代理添加成功',
                'data': {
                    'key': zlk_info['data']['key'],
                    'rtsp': f"rtsp://{ZLK_HOST}:8554/openUrl/{stream}",
                    'mp4': f"http://{ZLK_HOST}:8080/openUrl/{stream}.live.mp4",
                    'ts': f"http://{ZLK_HOST}:8080/openUrl/{stream}.live.ts",
                    'flv': f"http://{ZLK_HOST}:8080/openUrl/{stream}.live.flv",
                    'rtmp': f"rtmp://{ZLK_HOST}:1935/openUrl/{stream}"
                }
            })
        else:
            return web.json_response({
                'code': 400,
                'msg': zlk_info.get('msg', '添加流失败！'),
                'data': zlk_info.get('data')
            })

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！错误信息：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器异常：{str(e)}'})


# 关闭拉流代理
async def delStreamProxy(request):
    data = await request.post()
    key = data.get('key')

    if not key:
        return web.json_response({'code': 400, 'msg': '缺少必要参数 key'})

    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/delStreamProxy"
    params = {
        'secret': ZLK_SECRET,
        'key': key,
    }

    try:
        res = requests.get(api, params=params, timeout=2)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式非 JSON'})

        # 先尝试关闭流
        if zlk_info.get('code') == 0 and zlk_info.get('data', {}).get('flag'):
            try:
                async with AsyncSessionLocal() as session:
                    result = await session.execute(
                        select(Zlk_data).where(Zlk_data.zlk_key == key)
                    )
                    existing = result.scalar_one_or_none()

                    if existing:
                        await session.delete(existing)
                        await session.commit()
                        return web.json_response({'code': 200, 'msg': '关闭流成功并删除数据库记录！'})
                    else:
                        return web.json_response({'code': 400, 'msg': '该流不存在无法关闭！'})

            except Exception as e:
                return web.json_response({'code': 500, 'msg': f'服务器异常：{str(e)}'})
        else:
            msg = zlk_info.get('msg', '关闭流失败')
            return web.json_response({'code': 400, 'msg': msg})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！错误信息：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器异常：{str(e)}'})



# 获取流列表，可选筛选参数
async def getMediaList(request):
    data = await request.post()
    key = data.get('key')       # 用于后续扩展用
    schema = data.get('schema') # 可选协议：rtsp / rtmp

    # 拼接 ZLMediaKit 的接口地址
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/getMediaList"
    alk_secret = ZLK_SECRET

    params = {
        'secret': alk_secret
    }
    if schema:
        params['schema'] = schema

    try:
        # 加上 timeout（非常重要）
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()  # 非 200 抛异常

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': '响应内容不是合法 JSON'})

        if zlk_info.get('code') == 0 and zlk_info.get('data'):
            return web.json_response({
                'code': 200,
                'data': zlk_info['data']
            })
        else:
            return web.json_response({
                'code': 400,
                'msg': zlk_info.get('msg', 'ZLMediaKit 响应失败')
            })

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器异常：{str(e)}'})


# 获取某个流的观看者列表
async def getMediaPlayerList(request):
    data = await request.post()

    schema = data.get('schema') or 'rtmp'  # 默认协议 rtmp
    vhost = data.get('vhost') or '__defaultVhost__'
    app = data.get('app')
    stream = data.get('stream')

    if not app or not stream:
        return web.json_response({'code': 400, 'msg': '参数不完整，必须提供 app 和 stream'})

    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/getMediaPlayerList"
    params = {
        'secret': ZLK_SECRET,
        'schema': schema,
        'vhost': vhost,
        'app': app,
        'stream': stream
    }

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()  # 非 200 状态码会抛异常

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应内容不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 响应失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'未知错误：{str(e)}'})



# 工具方法：获取 ZLMediaKit 的拉流代理列表
def fetch_stream_proxy_list_sync():
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/listStreamProxy"
    params = {'secret': ZLK_SECRET}

    try:
        response = requests.get(api, params=params, timeout=5)  # 5秒超时
        response.raise_for_status()  # 状态码非200会抛异常

        json_data = response.json()
        if json_data.get("code") == 0:
            return json_data.get("data", [])
        else:
            print(f"接口返回错误: {json_data.get('msg')}")
            return []
    except requests.exceptions.Timeout:
        print("请求超时")
        return []
    except requests.exceptions.RequestException as e:
        print(f"请求异常: {e}")
        return []
    except Exception as e:
        print(f"未知异常: {e}")
        return []



# 获取拉流代理列表
async def listStreamProxy(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/listStreamProxy"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()  # 非 200 抛异常

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！错误信息：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器异常：{str(e)}'})

# 服务器配置
async def getServerConfig(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/getServerConfig"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 接口返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, '    msg': f'服务器不在线！请求错误：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器内部异常：{str(e)}'})



# ZLMediaKit 重启服务器
async def restartServer(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/restartServer"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('msg')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 接口返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！请求错误：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器内部异常：{str(e)}'})


# ZLMediaKit 获取各后台 epoll(或 select)线程负载以及延时
async def getWorkThreadsLoad(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/getWorkThreadsLoad"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 接口返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！请求错误：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器内部异常：{str(e)}'})



# ZLMediaKit 获取主要对象个数统计，主要用于分析内存性能
async def getStatistic(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/getStatistic"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 接口返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！请求错误：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器内部异常：{str(e)}'})

# ZLMediaKit 获取版本信息 如分支，commit id, 编译时间
async def version(request):
    api = f"http://{ZLK_HOST}:{ZLK_PORT}/index/api/version"
    params = {'secret': ZLK_SECRET}

    try:
        res = requests.get(api, params=params, timeout=1)
        res.raise_for_status()

        try:
            zlk_info = res.json()
        except Exception:
            return web.json_response({'code': 400, 'msg': 'ZLMediaKit 响应格式不是合法 JSON'})

        if zlk_info.get('code') == 0:
            return web.json_response({'code': 200, 'data': zlk_info.get('data')})
        else:
            return web.json_response({'code': 400, 'msg': zlk_info.get('msg', 'ZLMediaKit 接口返回失败')})

    except requests.exceptions.Timeout:
        return web.json_response({'code': 400, 'msg': '服务器不在线（请求超时）！'})

    except requests.exceptions.RequestException as e:
        return web.json_response({'code': 400, 'msg': f'服务器不在线！请求错误：{str(e)}'})

    except Exception as e:
        return web.json_response({'code': 500, 'msg': f'服务器内部异常：{str(e)}'})
